import shui.plugin
from struct import pack, calcsize
from shui.config import conf
from random import randint 
from logging import info, debug, warn, critical
from os.path import split, splitext

# For non-native mapping of dmap
class DMAPGeneric:
    def __init__(self, value, fmt):
        self.value = value
        self.fmt = fmt

class DMAPObject(object):
    def __init__(self, name):
        self.obj = (name, [])
        self.list = self.obj[1]
        self.lastcontainer = self.list
        self.containertree = []

    def addatomic(self, name, value):
        self.lastcontainer.append((name, value))
    
    def addatomiclist(self, lst=[]):
        for obj in lst:
            self.lastcontainer.append(obj)
        
    def addcontainer(self, name):
        current_object = (name, [])
        self.currentcontainer = current_object[1]
        self.lastcontainer.append(current_object)
        self.containertree.append(self.lastcontainer)
        self.lastcontainer = self.currentcontainer
    
    def closecontainer(self):
        self.lastcontainer = self.containertree.pop()
        if self.lastcontainer == None:
            self.lastcontainer = self.list

    def getobject(self):
        return self.obj
    
    def serialize(self, obj=None):
        if obj == None:
            obj = self.obj
        name, value = obj
        if type(value) == type(list()):
            val = ''
            for item in value:
                val = val + self.serialize(item)
            size = len(val)
            return pack('!4sI%(size)is' % {'size':size}, name, size, val)
        if type(value) == type(str()):
            size = len(value)
            return pack('!4sI%(size)is' % {'size':size}, name, size, value)
        if type(value) == type(int()):
            size = 4
            return pack('!4sII', name, size, value)
        if type(value) == type(float()):
            size = 8
            return pack('!4sIF', name, size, value)
        if type(value) == type(()): ## tuple for version
            size=4
            return pack('!4sIHH', name, size, value[0], value[1])
        if type(value) == type(long()):
            size = 8
            return pack('!4sIq', name, size, value)
        if type(value) == type(unicode()):
            value = value.encode('ascii','replace')
            size = len(value)
            return pack('!4sI%(size)is' % {'size':size}, name, size, value)
        if isinstance(value, DMAPGeneric):
            size = calcsize(value.fmt)
            return pack('!4sI%s' % value.fmt, name, size,  value.value)

    def hexprint(self):
        ret = self.serialize()
        st = ''
        for ch in ret:
            st = st + '%s ' % hex(ord(ch)).split('x')[1]
        return st



from pkg_resources import resource_string
class Handler(object):
    content_codes = resource_string(__name__, 'content-codes')
    def __init__(self, plg):
        self.plg = plg
        self.server_name = conf['Common']['name'] or 'Shui'

    def request(self, path, headers, args):
         
        if path == '/content-codes':
            return self.do_content_codes(headers, args)
        if path == '/server-info':
            return self.do_server_info(headers, args)
        if path == '/login':
            return self.do_login(headers, args)
        if path == '/databases':
            return self.do_databases(headers, args)
        if path == '/databases/1/items':
            return self.do_song_list(headers, args)
        if path == '/update':
            return self.do_update(headers, args)
        if path.find('/databases/1/items') >= 0:
            return self.do_song(path, headers, args)


    def do_content_codes(self, headers, *args):
        return self.content_codes

    def do_server_info(self, headers, *args):
        retobj  = DMAPObject('msrv')
        retobj.addatomic('mstt', 200)
        retobj.addatomic('mpro', 1)
        retobj.addatomic('apro', 1)
        retobj.addatomic('minm', self.server_name)
        return retobj.serialize()
        
    def do_login(self, headers, *args):
        sessionid = randint(0, 2147483647)
        info('new sessionid > %s' % sessionid)
        retobj = DMAPObject('mlog')
        retobj.addatomic('mstt', 200)
        retobj.addatomic('mlid', sessionid)
        return retobj.serialize()
    def do_update(self, headers, *args):
        retobj = DMAPObject('mupd')
        retobj.addatomic('mstt', 200)
        retobj.addatomic('musr', 1)
        return retobj.serialize()

    def do_databases(self, headers, args):
        retobj = DMAPObject('avdb')
        retobj.addatomic('mstt', 200)
        muty = DMAPGeneric(0, 'B')
        retobj.addatomic('muty', muty)
        retobj.addatomic('mtco', 1)
        retobj.addatomic('mrco', 1)
        retobj.addcontainer('mlcl')
        retobj.addcontainer('mlit')
        retobj.addatomic('miid', 1)
        retobj.addatomic('mper', 1L)
        retobj.addatomic('minm', self.server_name)
        retobj.addatomic('mimc', 20)
        retobj.addatomic('mctc', 1)
        return retobj.serialize()
    def do_song_list(self, headers, args):
        playlist = self.plg.gen_playlist()
        retobj = DMAPObject('apso')
        retobj.addatomic('mstt', 200)
        muty = DMAPGeneric(0, 'B')
        retobj.addatomic('muty', muty)
        retobj.addatomic('mtco', len(playlist))
        retobj.addatomic('mrco', len(playlist))
        retobj.addcontainer('mlcl')
        for song in playlist:
            retobj.addatomic('mlit',song)
        return  retobj.serialize()
            
    def do_song(self, path, headers, args):
        itemname = splitext(split(path)[1])[0] # item number
        itemfile = self.plg.play_item(int(itemname))
        return itemfile

    
    def do_logout(self, headers, args):
        pass
    




if __name__=='__main__':
    a = DMAPObject('msvr')
    a.addatomic('msnm', 'hello')
    a.addcontainer('ytos')
    a.addatomiclist([('msnm', 'test'), ('mstt', 200)])
    a.closecontainer()
   # print a.getobject()
    print a.serialize()
